<?php

namespace App\Libraries;

use Google\Auth\OAuth2;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Support\Facades\Cache;

class GeMini
{
    protected $project_id = 'jowo-ai';
    protected $model_id = 'gemini-1.5-pro-002';
    protected $location_id; #us-central1 美洲  asia-southeast1 新加坡
    protected $api_endpoint;

    public function __construct($location_id = 'us-central1')
    {
        $this->location_id = $location_id;
        $this->api_endpoint = $location_id . '-aiplatform.googleapis.com';
    }

    public function run($messages)
    {
        try {
            $access_token = $this->getAccessToken();
            if (empty($access_token)) {
                return false;
            }

            $headers = [
                'Content-Type' => 'application/json',
                'Authorization' => 'Bearer ' . $access_token
            ];
            // 请求参数
            $body = json_encode([
                'contents' => [
                    [
                        'role' => 'user',
                        'parts' => [
                            'text' => $messages
                        ]
                    ]
                ],
                'generationConfig' => [
                    'temperature' => 1,
                    'maxOutputTokens' => 8192,
                    'topP' => 0.95,
                    'seed' => 0,
                    /*'responseMimeType' => 'application/json',
                    'responseSchema' => [
                        'type' => 'OBJECT',
                        'properties' => [
                            'response' => [
                                'type' => 'STRING'
                            ]
                        ]
                    ]*/
                ],
                'safetySettings' => [
                    [
                        'category' => 'HARM_CATEGORY_HATE_SPEECH',
                        'threshold' => 'OFF'
                    ],
                    [
                        'category' => 'HARM_CATEGORY_DANGEROUS_CONTENT',
                        'threshold' => 'OFF'
                    ],
                    [
                        'category' => 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
                        'threshold' => 'OFF'
                    ],
                    [
                        'category' => 'HARM_CATEGORY_HARASSMENT',
                        'threshold' => 'OFF'
                    ]
                ]
            ]);

            $client = new Client([
                'timeout'  => 120, // 设置请求超时时间为10秒
                'connect_timeout' => 10, // 设置连接超时时间为5秒
            ]);
            $uri = 'https://%s/v1/projects/%s/locations/%s/publishers/google/models/%s:generateContent';
            $uri = sprintf($uri, $this->api_endpoint, $this->project_id, $this->location_id, $this->model_id);
            $response = $client->post($uri, [
                'headers' => $headers,
                'body' => $body
            ]);
            if ($response->getStatusCode() != 200) {
                return false;
            }
            $result = json_decode($response->getBody()->getContents(), true);
            return $result;
        } catch (RequestException $e) {
            dd($e->getMessage());
        } catch (ConnectException $e) {
            dd($e->getMessage());
        }
    }

    public function count_tokens($messages)
    {
        try {
            $access_token = $this->getAccessToken();
            if (empty($access_token)) {
                return false;
            }

            $headers = [
                'Content-Type' => 'application/json',
                'Authorization' => 'Bearer ' . $access_token
            ];
            // 请求参数
            $body = json_encode([
                'model' => 'projects/' . $this->project_id . '/locations/' . $this->location_id . '/publishers/google/models/'. $this->model_id,
                'contents' => [
                    [
                        'role' => 'user',
                        'parts' => [
                            'text' => $messages
                        ]
                    ]
                ],
                'generationConfig' => [
                    'temperature' => 1,
                    'maxOutputTokens' => 8192,
                    'topP' => 0.95,
                    'seed' => 0
                ],
            ]);

            $client = new Client([
                'timeout'  => 120, // 设置请求超时时间为10秒
                'connect_timeout' => 10, // 设置连接超时时间为5秒
            ]);
            $uri = "https://%s/v1/projects/%s/locations/%s/publishers/google/models/%s:countTokens";
            $uri = sprintf($uri, $this->api_endpoint, $this->project_id, $this->location_id, $this->model_id);
            $response = $client->post($uri, [
                'headers' => $headers,
                'body' => $body
            ]);
            if ($response->getStatusCode() != 200) {
                return false;
            }
            $result = json_decode($response->getBody()->getContents(), true);
            return $result;
        } catch (RequestException $e) {
            dd($e->getMessage());
        } catch (ConnectException $e) {
            dd($e->getMessage());
        }
    }

    private function getAccessToken()
    {
        $serviceAccountFile = base_path() . DIRECTORY_SEPARATOR . 'jowo-ai-48a50ae2c98d.json';
        if (!file_exists($serviceAccountFile)) {
            return false;
        }
        $access_token = Cache::get('gemini:access_token');
        if (!empty($access_token)) {
            return $access_token;
        }

        $serviceAccount = json_decode(file_get_contents($serviceAccountFile), true);
        $oauth2 = new OAuth2([
            'audience' => 'https://oauth2.googleapis.com/token',
            'issuer' => $serviceAccount['client_email'],
            'scope' => 'https://www.googleapis.com/auth/cloud-platform',
            'signingAlgorithm' => 'RS256',
            'signingKey' => $serviceAccount['private_key'],
            'sub' => $serviceAccount['client_email'],
            'tokenCredentialUri' => 'https://oauth2.googleapis.com/token'
        ]);

        $token = $oauth2->fetchAuthToken();
        Cache::put('gemini:access_token', $token['access_token'], $token['expires_in'] - 1800);
        return $token['access_token'];
    }
}
